<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Hassas kronometre ihtiyaçları için tasarlanmıştır.
 * Kullanmak için TimeTracker::startClock($isim) dedikten sonra TimeTracker::stopClock($isim) metodunun 
 * döndürdüğü stringi geçen süreyi göstermek için kullanabilirsiniz. Stop'tan önce ara adımları izlemek istiyorsanız
 * TimeTracker::getElapsedTimeString($isim) veya getElapsedTimeStringAsMillis($isim) metodlarını kullanabilirsiniz.
 * Start ile başlattığınız saatleri işiniz bittiğinde mutlaka Stop ile durdurmanız gerekiyor, çünkü ancak stop ile 
 * register edilmiş bir saat nesnesini unregister edebilirsiniz.
 *
 * @author Sedat Sevgili
 * tested in 25.12.2011 19:40
 */
class TimeTracker {
    //put your code here
    public static $MAX_TIMETRACKER_USERS = 500;
    private static $users = array();
    
    private static function getTimer($name) {
        if(!isset(self::$users[$name]) || is_null(self::$users[$name])) {
            return false;
        }
        return self::$users[$name];
    }
    
    /**
     * Yeni bir saat oluşturur ve listeye register eder.
     * @param string $name: saat adı
     */
    public static function startClock($name) {
        if(count(self::$users) > self::$MAX_TIMETRACKER_USERS) {
            throw new Exception("Max Saat izleyici sayısı aşıldı. (" . self::$MAX_TIMETRACKER_USERS . ")");
            return;
        }
        $timer = self::getTimer($name);
        if($timer) {
            throw new Exception($name . " isminde zaten bir zaman izleyici var");
        }
        $timer = new TimerElement($name);
        self::$users[$name] = $timer;
    }
 
    /**
     * İsmi verilen saat için başlangıçtan bu yana ne kadar zaman geçtiğini milisanye cinsinden döndürür.
     * @param string $name: saatin adı
     * @return int: bir önceki tick'ten bu yana geçen süre(milisaniye cinsinden)
     */
    public static function getElapsedTime($name) {
        $timer = self::getTimer($name);
        if(!$timer) {
            return -1;
        }
        $timer->refresh();
        return $timer->getElapsedTime();
    }
    
    /**
     * ismi verilen saatin en son kontrolünden bu yana ne kadar zaman geçtiğini milisaniye cinsinden döndürür.
     * @param string $name: saatin adı
     * @return int: Bir önceki tick'ten bu yana geçen süre(milisaniye cinsinden) 
     */
    public static function getTimeDelta($name) {
        $timer = self::getTimer($name);
        if(!$timer) {
            return -1;
        }
        $timer->refresh();
        return $timer->getDiff() / 1000;
    }
    
    /**
     * İsmi verilen saatin en son kontrolünden(başlangıç veya bir önceki tick) bu yana ne kadar zaman geçtiğini
     * ve başlangıçtan bu yana geçen süreyi virgülden önceki 3 basamaklı saniyeyi ifade eden string 
     * cinsinden döndürür.
     * @param string $name: saatin adı
     * @return string: Bir önceki tick'ten bu yana geçen süre(binde bir hassasiyetli saniye cinsinden) 
     */
    public static function getElapsedTimeString($name) {
        $timer = self::getTimer($name);
        if(!$timer) {
            throw new Exception("Geçersiz kronometre: " . $name);
        }
        $timer->refresh();
        return "Delta: " . floatval($timer->getDiff() / 1000) . " s. Elapsed: " . floatval($timer->getElapsedTime() / 1000) . " s.";
    }
    
    /**
     * 
     * @param string $name: saatin adı
     * @return string: bir önceki tick'ten bu yana geçen süre(milisaniye cinsinden) 
     */
    public static function getElapsedTimeStringAsMillis($name) {
        $timer = self::getTimer($name);
        if(!$timer) {
            throw new Exception("Geçersiz kronometre: " . $name);
        }
        $timer->refresh();
        return "Delta: " . ($timer->getDiff() / 1000) . "ms. Elapsed: " . ($timer->getElapsedTime() / 1000) . "ms.";
    }
    
    /**
     * 
     * @param string $name: saatin adı
     * @param int $itemCount: süre zarfında işlenen nesne sayısı
     * @return int: başlangıçtan bu yana işlenen saniyedeki eleman sayısı 
     */
    public static function getItemsPerSecond($name, $itemCount) {
        $timer = self::getTimer($name);
        if(!$timer) {
            return -1;
        }
        $timer->refresh();
        $items = 0;
        if($timer->getElapsedTime() > 0) {
            $items  =  ($itemCount * 1000) / $timer->getElapsedTime();
        return $items;
        }
    }
    
    /**
     * Saati durduru ve başlangıçtan bu yana geçen süreyi saniye ve ms cinsinden döndürür. Ayrıca
     * saati listeden siler.
     * @param string $name: saat ismi
     * @return string: başlangıçtan bu yana geçen süre 
     */
    public static function stopClock($name) {
        $timer = self::getTimer($name);
        if(!$timer) {
            throw new Exception("Geçersiz Kronometre: " . $name);
        }
        $timer->refresh();
        unset(self::$users[$name]);
        return floatval($timer->elapsedTime) . "sn." . " (" . $timer->elapsedTime . "ms.)";
    }
}

/**
 * İsimlendirilmiş zaman bilgisi taşıyıcı.
 */
class TimerElement {
    
    public $name;
    public $startTime;
    public $stopTime;
    public $lastTime;
    public $creationTime;
    public $elapsedTime;
    public $diff;
    
    private static function getMilis() {
        return time() / 1000;
    }
    
    function __construct($name) {
        $this->creationTime = self::getMilis();
        $this->startTime = $this->creationTime;
        $this->lastTime = $this->creationTime;
        $this->name = $name;
    }
    
    public function refresh() {
        $this->diff = self::getMilis() - $this->lastTime;
        $this->lastTime = self::getMilis();
        $this->elapsedTime = $this->lastTime - $this->startTime;
    }
    
    public function getDiff() {
        return $this->diff;
    }
    
    public function getElapsedTime() {
        return $this->elapsedTime;
    }
    
    public function getLastTime() {
        return $this->lastTime;
    }
    
    public function getName() {
        return $this->name;
    }
    
    public function getStartTime() {
        return $this->startTime;
    }
    
    public function getStopTime() {
        return $this->stopTime;
    }
}

















